package com.bjpowernode.config.filter;

import cn.hutool.json.JSONUtil;
import com.bjpowernode.constant.Constants;
import com.bjpowernode.entity.TUser;
import com.bjpowernode.manager.JwtManager;
import com.bjpowernode.manager.RedisManager;
import com.bjpowernode.result.CodeEnum;
import com.bjpowernode.result.R;
import com.bjpowernode.util.ResponseUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.lang.ref.ReferenceQueue;
import java.util.concurrent.TimeUnit;

/**
 * 验证jwt是否合法
 *
 * jwt合法说明用户登录过了，否则表示用户没有登录
 *
 */
@Component
public class JwtFilter extends OncePerRequestFilter {

    @Resource
    private JwtManager jwtManager;

    @Resource
    private RedisManager redisManager;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        response.setCharacterEncoding("UTF-8");

        //从请求头中拿到token
        String token = request.getHeader("Authorization");

        //如果是登录请求，不需要验证token，因为登录请求还没有生成token，所以不要拦截登录请求
        String requestUri = request.getRequestURI();

        if (requestUri.equals(Constants.LOGIN_URI)) {
            //让Filter继续往下执行，执行下一个Filter
            filterChain.doFilter(request, response);
        } else {
            //验证token是否合法
            if (!StringUtils.hasText(token)) {
                R result = R.FAIL(CodeEnum.LOGIN_TOKEN_EMPTY);
                ResponseUtil.write(response, result);

            } else if (!jwtManager.verifyToken(token)) {
                R result = R.FAIL(CodeEnum.LOGIN_TOKEN_ILLEGAL);
                ResponseUtil.write(response, result);

            } else {
                //比较一下和redis的token是否相等
                String userJSON = jwtManager.parseToken(token);
                TUser tUser = JSONUtil.toBean(userJSON, TUser.class);

                //拿到了redis中的token
                String redisToken = (String)redisManager.getValue(Constants.REDIS_LOGIN_TOKEN + tUser.getId());
                if (!token.equals(redisToken)) {
                    R result = R.FAIL(CodeEnum.LOGIN_TOKEN_ERROR);
                    ResponseUtil.write(response, result);

                } else {
                    //token验证通过了，要在spring security的上下文中放入当前用户的认证信息
                    UsernamePasswordAuthenticationToken authenticationToken =
                            new UsernamePasswordAuthenticationToken(tUser, tUser.getLoginPwd(), AuthorityUtils.NO_AUTHORITIES);
                    SecurityContextHolder.getContext().setAuthentication(authenticationToken);

                    //token验证通过了，刷新token的过期时间 (30分钟？ 7天？ 需要进行判断)
                    Boolean rememberMe = Boolean.parseBoolean(request.getHeader("rememberMe"));
                    if (rememberMe) {
                        redisManager.flushKeyExpireTime(Constants.REDIS_LOGIN_TOKEN + tUser.getId(), 7, TimeUnit.DAYS);
                    } else {
                        redisManager.flushKeyExpireTime(Constants.REDIS_LOGIN_TOKEN + tUser.getId(), 30, TimeUnit.MINUTES);
                    }

                    //让Filter继续往下执行，执行下一个Filter
                    filterChain.doFilter(request, response);
                }
            }
        }
    }
}
